package ngat.oss.simulation;

import ngat.phase2.*;
import ngat.util.logging.*;
import java.util.*;

public class BasicAccountingModel implements AccountingModel {
  
   
    private Map accounts;

    LogProxy logger;

    double wdp = 180;
    double wda = 200;
    double wdx = 220;

    double wbp = 100;
    double wba = 120;
    double wbx = 140;

    double wp = 400;

    public BasicAccountingModel() {

	accounts = new HashMap();

	Logger slogger = LogManager.getLogger("SIM");
	logger = new LogProxy("BAM","",slogger);
    }

//     /** Return a list <Account> of proposal's accounts.*/
//     public Iterator listAccounts(String path) throws Exception {
// 	Map pac = (Map)accounts.get(path);
// 	if (pac == null) 
// 	    return null;
// 	return pac.values().iterator();
//     }
    
    /** Get a specific proposal account by ID.*/
    public Accounts getAccounts(String path) throws Exception {
	Accounts acc = (Accounts)accounts.get(path);
	if (acc == null) {
	    acc = new Accounts();
	    accounts.put(path, acc);
	 }
	return acc;
    }

//     /** Add a new proposal account.*/
//     public void addAccount(String path, int acId, Account account) throws Exception {
// 	Map pac = (Map)accounts.get(path);
// 	if (pac == null) {
// 	    pac = new HashMap();
// 	    accounts.put(path, pac);
// 	}
// 	pac.put(new Integer(acId), account);
//     }

//     /** Delete a proposal account.*/
//     public void removeAccount(String path, int acId) throws Exception {
// 	Map pac = (Map)accounts.get(path);
// 	if (pac == null) 
// 	    return;
// 	pac.remove(new Integer(acId));	
//     }
    
    /** Convert an (L,S) pair into an account ID - works for crap seeing also.*/
    public int getAcId(int lunar, int seeing) {
	return 4*lunar+seeing+1;
    }
    
    /** Load the accounts from the supplied ODB cache for executions prior to time.*/
    public void loadAccounts(Phase2Model phase2, long time) throws Exception {
 
	long st = System.currentTimeMillis();
        int nh = 0;
	
        Iterator ip = phase2.listProposals();
        while (ip.hasNext()) {
	    
            try {

                Proposal proposal = (Proposal)ip.next();
		String path = proposal.getFullPath();
                if (proposal == null) continue;

		Accounts pac = getAccounts(path); // create them
				       
		Account total = new Account((double)proposal.getAllocatedTime(), (double)proposal.getUsedTime());
		pac.addAccount(ACCOUNT_TOTAL, total);
		//		System.err.println("Proposal: "+proposal.getFullPath()+" -> Add account: "+ACCOUNT_TOTAL+" "+total);

		createAccount(pac, proposal, Group.BRIGHT, Group.EXCELLENT);
		createAccount(pac, proposal, Group.BRIGHT, Group.AVERAGE);
		createAccount(pac, proposal, Group.BRIGHT, Group.POOR);
		createAccount(pac, proposal, Group.BRIGHT, Group.CRAP);

		createAccount(pac, proposal, Group.DARK, Group.EXCELLENT);
		createAccount(pac, proposal, Group.DARK, Group.AVERAGE);
		createAccount(pac, proposal, Group.DARK, Group.POOR);
		createAccount(pac, proposal, Group.DARK, Group.CRAP);

		createBiddingAccount(pac, proposal);

		logger.method("loadAccounts").log(2,"Checking accounts for Proposal: "+proposal.getFullPath()+"...");
		logger.method("loadAccounts").log(2," Accs = "+getAccounts(proposal.getFullPath()));
		logger.method("loadAccounts").log(2," Total: "+getAccounts(proposal.getFullPath()).getAccount(ACCOUNT_TOTAL));		   
		logger.method("loadAccounts").log(2," BidFund : "+getAccounts(proposal.getFullPath()).getAccount(10));
		
		
	    } catch (Exception e) {
		e.printStackTrace();
            }
	}

    }

    private void createAccount(Accounts accs, Proposal proposal, int lunar, int seeing) throws Exception {
	double alloc = 1.0;
	double used  = 0.0;
	if (seeing != Group.CRAP) {	 
	    double ta = (double)proposal.getAllocatedTime();
	    alloc = (double)proposal.getAllocatedFraction(lunar, seeing)*ta;
	    used  = (double)proposal.getTimeUsed(lunar, seeing);
	}

	Account acc = new Account(alloc, used);
	int acid = getAcId(lunar, seeing);
	accs.addAccount(10, acc);
	logger.method("createAccount(ac,p,l,s)").log(2,"Proposal: "+proposal.getFullPath()+" -> Add account: "+acid+" "+acc);
    }
    
    private void createBiddingAccount(Accounts accs, Proposal proposal) throws Exception {

	double used = 0.0;
	double ta = (double)proposal.getAllocatedTime();
	double allocDP = (double)proposal.getAllocatedFraction(Group.DARK, Group.POOR)*ta;
	double allocDA = (double)proposal.getAllocatedFraction(Group.DARK, Group.AVERAGE)*ta;
	double allocDX = (double)proposal.getAllocatedFraction(Group.DARK, Group.EXCELLENT)*ta;

	double allocBP = (double)proposal.getAllocatedFraction(Group.BRIGHT, Group.POOR)*ta;
        double allocBA = (double)proposal.getAllocatedFraction(Group.BRIGHT, Group.AVERAGE)*ta;
        double allocBX = (double)proposal.getAllocatedFraction(Group.BRIGHT, Group.EXCELLENT)*ta;

	double scip = (double)proposal.getPriority();
	double alloc = wdp*allocDP + wda*allocDA +wdx*allocDX + wbp*allocBP + wba*allocBA + wbx*allocBX +wp*scip;
  
	Account acc = new Account(alloc, used);
        int acid = 10;
        accs.addAccount(acid, acc);
        logger.method("createAccount(ac,p,l,s)").
	    log(2,"Proposal: "+proposal.getFullPath()+" -> Add account: "+acid+" "+acc);
    
    
    }

}
